package timing.ukulele.handler;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.server.WebFilterExchange;
import org.springframework.security.web.server.authentication.WebFilterChainServerAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import timing.ukulele.config.JwtProperties;
import timing.ukulele.entity.AuthUserDetail;
import timing.ukulele.service.SecurityUserDetailService;
import timing.ukulele.util.JWtUtil;
import timing.ukulele.vo.ResponseResult;

import java.util.HashMap;
import java.util.Map;

@Component
public class AuthenticationSuccessHandler extends WebFilterChainServerAuthenticationSuccessHandler {

    private final JwtProperties jwtProperties;

    public AuthenticationSuccessHandler(JwtProperties jwtProperties) {
        this.jwtProperties = jwtProperties;
    }


    @Override
    public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) {
        ServerWebExchange exchange = webFilterExchange.getExchange();
        ServerHttpResponse response = exchange.getResponse();
        HttpHeaders headers = response.getHeaders();
        headers.add("Content-Type", "application/json;charset=UTF-8");
        headers.add("Cache-Control", "no-store,no-cache,must-revalidate,max-age-8");
        ResponseResult<AuthUserDetail> result = ResponseResult.success();
        byte[] dataBytes = {};
        ObjectMapper mapper = new ObjectMapper();
        try {
            User user = (User) authentication.getPrincipal();
            AuthUserDetail userDetails = buildUser(user);
            Map<String, Object> map = new HashMap<>(2);
            map.put("user-info", userDetails);
            String jwtToken = JWtUtil.createJavaWebToken4JwtAuth(map, jwtProperties.getSecretKey(), jwtProperties.getValidateInMs());
            map.put("X-TOKEN", jwtToken);
            userDetails.setToken(jwtToken);
            result.setData(userDetails);
            dataBytes = mapper.writeValueAsBytes(result);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        DataBuffer body = response.bufferFactory().wrap(dataBytes);
        return response.writeWith(Mono.just(body));
    }

    private AuthUserDetail buildUser(User user) {
        AuthUserDetail authUserDetail = new AuthUserDetail();
        authUserDetail.setUsername(user.getUsername());
        authUserDetail.setPassword(new BCryptPasswordEncoder().encode("123456"));
        authUserDetail.setRole("admin");
        return authUserDetail;
    }
}
